import React, { useState, useEffect, useRef } from 'react'
import { User, Save, Plus } from 'lucide-react'
import { experimentPlanningAPI } from '../services/api'  // 导入API服务
import AddExperimentModal from './AddExperimentModal'  // 导入添加试验弹窗组件

const ExperimentPlanning = () => {
  // 系统数据（只读，不可拖拽）
  const [systemData, setSystemData] = useState({
    整星试验: [],
    单机试验: [],
    自建试验: []
  })
  
  // 可调整数据（可拖拽）
  const [adjustableData, setAdjustableData] = useState({
    整星试验: [],
    单机试验: [],
    自建试验: []
  })
  const [startDate, setStartDate] = useState(new Date())
  const [dragState, setDragState] = useState(null)
  const ganttContainerRef = useRef(null)
  const startDateRef = useRef(new Date())

  // 设备列表状态 - 从API获取
  const [equipments, setEquipments] = useState([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
  
  // 保存按钮状态
  const [saveStatus, setSaveStatus] = useState('idle') // 'idle', 'saving', 'success', 'error'
  
  // Tooltip状态
  const [tooltip, setTooltip] = useState({ visible: false, x: 0, y: 0, content: null })

  // 编辑弹窗状态
  const [editModalVisible, setEditModalVisible] = useState(false)
  const [editingExperiment, setEditingExperiment] = useState(null)
  const [editForm, setEditForm] = useState({
    experiment_name: '',
    enter: '',
    end: ''
  })

  // 添加试验弹窗状态
  const [addModalVisible, setAddModalVisible] = useState(false)
  
  // 右键菜单状态
  const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0, experiment: null, type: '', equipment: '' })

  // 编辑弹窗处理函数
  const handleEditExperiment = (experiment, type, equipment) => {
    console.log('🔧 打开编辑弹窗:', {
      experiment,
      type,
      equipment: equipment?.name || equipment?.equipment_name
    })
    
    setEditingExperiment({ ...experiment, type, equipment })
    setEditForm({
      experiment_name: experiment.experiment_name || experiment.name || experiment.experiment_report_name || '试验名称',
      enter: experiment.enter || '',
      end: experiment.end || ''
    })
    setEditModalVisible(true)
  }

  const handleCloseEditModal = () => {
    setEditModalVisible(false)
    setEditingExperiment(null)
    setEditForm({
      experiment_name: '',
      enter: '',
      end: ''
    })
  }

  // 添加试验弹窗处理函数
  const handleOpenAddModal = () => {
    setAddModalVisible(true)
  }

  const handleCloseAddModal = () => {
    setAddModalVisible(false)
  }

  // 右键菜单处理函数
  const handleContextMenu = (e, experiment, type, equipment) => {
    e.preventDefault()
    e.stopPropagation()
    
    setContextMenu({
      visible: true,
      x: e.clientX,
      y: e.clientY,
      experiment,
      type,
      equipment
    })
  }

  const hideContextMenu = () => {
    setContextMenu({ visible: false, x: 0, y: 0, experiment: null, type: '', equipment: '' })
  }

  // 删除试验计划
  const handleDeleteExperiment = async (experiment) => {
    if (!experiment.id) {
      console.error('试验计划ID不存在')
      return
    }

    if (!window.confirm(`确定要删除试验计划"${experiment.experiment_name || experiment.experiment_report_name || '未知试验'}"吗？`)) {
      return
    }

    try {
      await experimentPlanningAPI.experimentPlan.delete(experiment.id)
      
      // 重新加载数据
      await loadExperimentData()
      
      // 隐藏右键菜单
      hideContextMenu()
      
      console.log('试验计划删除成功')
    } catch (error) {
      console.error('删除试验计划失败:', error)
      alert('删除失败，请重试')
    }
  }

  const handleAddExperiment = (newExperiment) => {
    console.log('✅ 新试验添加成功:', newExperiment)
    
    // 根据试验类型添加到对应的可调整数据中
    const typeMapping = {
      '整星': '整星试验',
      '单机': '单机试验', 
      '自建': '自建试验'
    }
    const experimentType = typeMapping[newExperiment.experiment_type] || '整星试验'
    
    setAdjustableData(prev => ({
      ...prev,
      [experimentType]: [
        ...(prev[experimentType] || []),
        {
          ...newExperiment,
          is_adjustable: true,
          experiment_name: newExperiment.experiment_name || newExperiment.project_name
        }
      ]
    }))
    
    // 同时添加到系统数据中以保持数据一致性
    setSystemData(prev => ({
      ...prev,
      [experimentType]: [
        ...(prev[experimentType] || []),
        {
          ...newExperiment,
          is_adjustable: true,
          experiment_name: newExperiment.experiment_name || newExperiment.project_name
        }
      ]
    }))
    
    // 刷新数据以获取最新的试验列表
    loadExperimentData()
  }

  // Tooltip处理函数
  const showTooltip = (e, experiment, type, equipment) => {
    const rect = e.currentTarget.getBoundingClientRect()
    const content = {
      experiment_name: experiment.experiment_name || experiment.name || experiment.experiment_report_name || '未知试验',
      enter_date: experiment.enter || experiment.enter_date || '未设置',
      end_date: experiment.end || experiment.end_date || '未设置'
    }
    
    setTooltip({
      visible: true,
      x: rect.left + rect.width / 2,
      y: rect.top - 10,
      content
    })
  }
  
  const hideTooltip = () => {
    setTooltip({ visible: false, x: 0, y: 0, content: null })
  }

  const handleSaveEdit = async () => {
    if (!editingExperiment) return
    
    try {
      console.log('💾 保存编辑:', {
        实验ID: editingExperiment.id,
        原始数据: editingExperiment,
        编辑数据: editForm
      })
      
      // 更新可调整数据
      setAdjustableData(prev => {
        const newData = { ...prev }
        const expType = editingExperiment.type
        
        if (newData[expType]) {
          newData[expType] = newData[expType].map(exp => {
            if (exp.id === editingExperiment.id) {
              return {
                ...exp,
                experiment_name: editForm.experiment_name,
                name: editForm.experiment_name, // 兼容不同字段名
                enter: editForm.enter,
                end: editForm.end,
                // 自动调整开始时间和完成时间，确保在入场和出场时间范围内
                start: exp.start < editForm.enter ? editForm.enter : (exp.start > editForm.end ? editForm.end : exp.start),
                complete: exp.complete < editForm.enter ? editForm.enter : (exp.complete > editForm.end ? editForm.end : exp.complete)
              }
            }
            return exp
          })
        }
        
        return newData
      })
      
      handleCloseEditModal()
      
    } catch (error) {
      console.error('保存编辑失败:', error)
      alert('保存失败，请重试')
    }
  }

  // 判断是否为节假日（简化版本，实际应用中可以接入节假日API）
  const isHoliday = (date) => {
    // 这里可以添加具体的节假日判断逻辑
    // 暂时返回false，实际使用时可以接入节假日API
    return false
  }

  // 判断是否为过去日期
  const isPastDate = (date) => {
    const today = new Date()
    today.setHours(0, 0, 0, 0)
    const compareDate = new Date(date)
    compareDate.setHours(0, 0, 0, 0)
    return compareDate < today
  }

  // 验证并调整试验时间，确保开始时间和完成时间在入场时间和出场时间范围内
  const validateAndAdjustExperimentTimes = (dates) => {
    const adjustedDates = { ...dates }
    const enterDate = new Date(adjustedDates.enter)
    const startDate = new Date(adjustedDates.start)
    const completeDate = new Date(adjustedDates.complete)
    const endDate = new Date(adjustedDates.end)
    
    // 定义最小间隔（1天），防止拖动条重叠
    const MIN_INTERVAL_DAYS = 1
    const MIN_INTERVAL_MS = MIN_INTERVAL_DAYS * 24 * 60 * 60 * 1000
    
    // 首先确保入场时间和出场时间的约束
    // 如果开始时间早于入场时间，调整开始时间为入场时间
    if (startDate < enterDate) {
      adjustedDates.start = adjustedDates.enter
    }
    
    // 如果完成时间晚于出场时间，调整完成时间为出场时间
    if (completeDate > endDate) {
      adjustedDates.complete = adjustedDates.end
    }
    
    // 如果完成时间早于入场时间，调整完成时间为入场时间
    if (completeDate < enterDate) {
      adjustedDates.complete = adjustedDates.enter
    }
    
    // 核心约束：确保开始时间和完成时间之间有最小间隔，防止拖动条重叠
    const newStartDate = new Date(adjustedDates.start)
    const newCompleteDate = new Date(adjustedDates.complete)
    
    // 计算时间差
    const timeDiff = newCompleteDate.getTime() - newStartDate.getTime()
    
    if (timeDiff < MIN_INTERVAL_MS) {
      // 如果时间间隔小于最小间隔，需要调整
      const midPoint = new Date((newStartDate.getTime() + newCompleteDate.getTime()) / 2)
      
      // 计算调整后的开始时间和完成时间
      const adjustedStartTime = midPoint.getTime() - MIN_INTERVAL_MS / 2
      const adjustedCompleteTime = midPoint.getTime() + MIN_INTERVAL_MS / 2
      
      // 检查调整后的时间是否在有效范围内
      const minTime = enterDate.getTime()
      const maxTime = endDate.getTime()
      
      if (adjustedStartTime >= minTime && adjustedCompleteTime <= maxTime) {
        // 如果调整后的时间都在范围内，使用调整后的时间
        adjustedDates.start = new Date(adjustedStartTime).toISOString().split('T')[0]
        adjustedDates.complete = new Date(adjustedCompleteTime).toISOString().split('T')[0]
      } else {
        // 如果调整后超出范围，采用边界策略
        if (newStartDate.getTime() === newCompleteDate.getTime()) {
          // 如果开始时间和完成时间相同，向后推完成时间
          const newCompleteTime = Math.min(newStartDate.getTime() + MIN_INTERVAL_MS, maxTime)
          adjustedDates.complete = new Date(newCompleteTime).toISOString().split('T')[0]
          
          // 如果推后完成时间后仍然没有足够间隔，向前推开始时间
          if (newCompleteTime - newStartDate.getTime() < MIN_INTERVAL_MS) {
            const newStartTime = Math.max(newCompleteTime - MIN_INTERVAL_MS, minTime)
            adjustedDates.start = new Date(newStartTime).toISOString().split('T')[0]
          }
        }
      }
    }
    
    // 再次检查边界约束
    const finalStartDate = new Date(adjustedDates.start)
    const finalCompleteDate = new Date(adjustedDates.complete)
    
    // 确保开始时间不晚于出场时间
    if (finalStartDate > endDate) {
      adjustedDates.start = adjustedDates.end
      // 如果调整后开始时间等于出场时间，完成时间也应该是出场时间
      if (finalCompleteDate < finalStartDate) {
        adjustedDates.complete = adjustedDates.end
      }
    }
    
    return adjustedDates
  }

  // 获取基于任务时间范围的日期范围
  const getMonthDates = () => {
    const dates = []
    
    // 获取所有任务的最早和最晚时间
    const allExperiments = [
      ...(systemData.整星试验 || []),
      ...(systemData.单机试验 || []),
      ...(systemData.自建试验 || []),
      ...(adjustableData.整星试验 || []),
      ...(adjustableData.单机试验 || []),
      ...(adjustableData.自建试验 || [])
    ]
    
    if (allExperiments.length === 0) {
      // 如果没有任务数据，使用默认范围
      const current = new Date(startDate)
      for (let i = 0; i < 365; i++) {
        dates.push(new Date(current))
        current.setDate(current.getDate() + 1)
      }
      return dates
    }
    
    // 找到所有任务的最早和最晚日期
    let earliestDate = null
    let latestDate = null
    
    allExperiments.forEach(exp => {
      const dates = [exp.enter, exp.start, exp.complete, exp.end].filter(Boolean)
      dates.forEach(dateStr => {
        const date = new Date(dateStr)
        if (!earliestDate || date < earliestDate) {
          earliestDate = date
        }
        if (!latestDate || date > latestDate) {
          latestDate = date
        }
      })
    })
    
    // 如果找不到有效日期，使用默认范围
    if (!earliestDate || !latestDate) {
      const current = new Date(startDate)
      for (let i = 0; i < 365; i++) {
        dates.push(new Date(current))
        current.setDate(current.getDate() + 1)
      }
      return dates
    }
    
    // 在最早和最晚日期基础上各扩展15天
    const startRange = new Date(earliestDate)
    startRange.setDate(startRange.getDate() - 15)
    
    const endRange = new Date(latestDate)
    endRange.setDate(endRange.getDate() + 15)
    
    // 生成日期范围
    const current = new Date(startRange)
    while (current <= endRange) {
      dates.push(new Date(current))
      current.setDate(current.getDate() + 1)
    }
    
    return dates
  }

  // 处理滚轮事件
  const handleWheel = (e) => {
    if (e.shiftKey && ganttContainerRef.current) {
      // Shift+滚轮：横向滚动，设备列冻结，支持无限制滚动
      e.preventDefault()
      const dateHeader = ganttContainerRef.current.querySelector('.date-header-scroll')
      const contentArea = ganttContainerRef.current.querySelector('.content-area-scroll')
      
      if (dateHeader && contentArea) {
        const scrollAmount = e.deltaY * 2 // 增加滚动速度
        const newScrollLeft = dateHeader.scrollLeft + scrollAmount
        
        // 检查是否需要扩展日期范围
        const maxScrollLeft = dateHeader.scrollWidth - dateHeader.clientWidth
        
        // 如果滚动到接近右边界，扩展日期范围
        if (newScrollLeft > maxScrollLeft * 0.8) {
          const newStartDate = new Date(startDate)
          newStartDate.setDate(newStartDate.getDate() + 15) // 向前扩展15天
          setStartDate(newStartDate)
          startDateRef.current = newStartDate
        }
        // 如果滚动到接近左边界，向后扩展日期范围
        else if (newScrollLeft < maxScrollLeft * 0.2 && startDate > new Date('2020-01-01')) {
          const newStartDate = new Date(startDate)
          newStartDate.setDate(newStartDate.getDate() - 15) // 向后扩展15天
          setStartDate(newStartDate)
          startDateRef.current = newStartDate
        }
        
        dateHeader.scrollLeft = newScrollLeft
        contentArea.scrollLeft = newScrollLeft
      }
    }
    // 普通滚轮：竖向滚动，设备列与甘特图同步（不阻止默认行为）
  }

  // 同步横向滚动
  const handleHorizontalScroll = (e) => {
    const scrollLeft = e.target.scrollLeft
    const dateHeader = ganttContainerRef.current.querySelector('.date-header-scroll')
    const contentArea = ganttContainerRef.current.querySelector('.content-area-scroll')
    
    if (dateHeader && e.target !== dateHeader) {
      dateHeader.scrollLeft = scrollLeft
    }
    if (contentArea && e.target !== contentArea) {
      contentArea.scrollLeft = scrollLeft
    }
  }

  useEffect(() => {
    const container = ganttContainerRef.current
    if (container) {
      container.addEventListener('wheel', handleWheel)  // 移除 {passive: false} 以避免警告
      return () => {
        container.removeEventListener('wheel', handleWheel)
      }
    }
  }, [])

  // 移除右键菜单相关的useEffect

  // 计算时间段在甘特图中的位置
  const getTimePosition = (dateStr, monthDates) => {
    const date = new Date(dateStr)
    const firstDay = monthDates[0]
    const dayIndex = Math.floor((date - firstDay) / (24 * 60 * 60 * 1000))
    
    if (dayIndex < 0 || dayIndex >= monthDates.length) {
      return null
    }
    
    return `${(dayIndex / monthDates.length) * 100}%`
  }

  // 获取时间段的宽度和位置
  const getExperimentPosition = (experiment, monthDates) => {
    const firstDay = monthDates[0]
    const lastDay = monthDates[monthDates.length - 1]
    const enterDate = new Date(experiment.enter)
    const endDate = new Date(experiment.end)
    
    // 计算在当前显示范围内的实际开始和结束位置
    const displayStart = enterDate < firstDay ? firstDay : enterDate
    const displayEnd = endDate > lastDay ? lastDay : endDate
    
    // 如果整个时间段都在当前显示范围之外，返回 null
    if (endDate < firstDay || enterDate > lastDay) {
      return null
    }
    
    const startIndex = Math.floor((displayStart - firstDay) / (24 * 60 * 60 * 1000))
    const endIndex = Math.floor((displayEnd - firstDay) / (24 * 60 * 60 * 1000))
    const width = endIndex - startIndex + 1 // 包含结束日
    
    return {
      left: `${(startIndex / monthDates.length) * 100}%`,
      width: `${(width / monthDates.length) * 100}%`,
      isPartial: enterDate < firstDay || endDate > lastDay // 标记是否为部分显示
    }
  }

  // 拖拽处理
  const handleMouseDown = (e, experiment, type, equipment) => {
    e.preventDefault()
    const rect = e.currentTarget.parentElement.getBoundingClientRect()
    const startX = e.clientX
    
    const originalDates = {
      enter: experiment.enter,
      start: experiment.start,
      complete: experiment.complete,
      end: experiment.end
    }
    
    // 记录拖动前的时间
    console.log('🔄 开始拖动任务块 - 完整对象信息:', {
      experiment对象: experiment,
      equipment对象: equipment,
      type: type
    })
    
    console.log('🔄 开始拖动任务块:', {
      设备: equipment?.name || equipment?.equipment_name || '未知设备',
      试验类型: type,
      试验名称: experiment?.experiment_name || experiment?.name || '未知试验',
      拖动前时间: {
        入场时间: originalDates.enter,
        开始时间: originalDates.start,
        完成时间: originalDates.complete,
        出场时间: originalDates.end
      }
    })
    
    setDragState({
      experiment,
      type,
      equipment,
      startX,
      containerRect: rect,
      originalDates
    })
  }

  const handleMouseMove = (e) => {
    if (!dragState) return
    
    const deltaX = e.clientX - dragState.startX
    const containerWidth = dragState.containerRect.width
    const monthDates = getMonthDates()
    const daysToMove = Math.round((deltaX / containerWidth) * monthDates.length)
    
    if (daysToMove === 0) return
    
    let newDates = {}
    
    if (dragState.timeKey) {
      // 单独拖拽某个时间点
      Object.keys(dragState.originalDates).forEach(key => {
        if (key === dragState.timeKey) {
          const originalDate = new Date(dragState.originalDates[key])
          originalDate.setDate(originalDate.getDate() + daysToMove)
          newDates[key] = originalDate.toISOString().split('T')[0]
        } else {
          newDates[key] = dragState.originalDates[key]
        }
      })
      
      // 特殊处理：拖拽开始时间或完成时间时的约束，防止拖动条重叠
      const MIN_INTERVAL_MS = 24 * 60 * 60 * 1000 // 1天的毫秒数
      
      if (dragState.timeKey === 'start') {
        // 拖拽开始时间时，确保与完成时间保持最小间隔
        const newStartDate = new Date(newDates.start)
        const completeDate = new Date(newDates.complete)
        const maxAllowedStartTime = completeDate.getTime() - MIN_INTERVAL_MS
        
        if (newStartDate.getTime() > maxAllowedStartTime) {
          newDates.start = new Date(maxAllowedStartTime).toISOString().split('T')[0]
        }
      } else if (dragState.timeKey === 'complete') {
        // 拖拽完成时间时，确保与开始时间保持最小间隔
        const startDate = new Date(newDates.start)
        const newCompleteDate = new Date(newDates.complete)
        const minAllowedCompleteTime = startDate.getTime() + MIN_INTERVAL_MS
        
        if (newCompleteDate.getTime() < minAllowedCompleteTime) {
          newDates.complete = new Date(minAllowedCompleteTime).toISOString().split('T')[0]
        }
      }
    } else {
      // 整体拖拽甘特图
      Object.keys(dragState.originalDates).forEach(key => {
        const originalDate = new Date(dragState.originalDates[key])
        originalDate.setDate(originalDate.getDate() + daysToMove)
        newDates[key] = originalDate.toISOString().split('T')[0]
      })
    }
    
    // 验证时间约束：开始时间和完成时间不能超过入场时间和出场时间
    const validatedDates = validateAndAdjustExperimentTimes(newDates)
    
    // 使用统一的字段名
    const finalDates = {
      enter: validatedDates.enter,
      start: validatedDates.start,
      complete: validatedDates.complete,
      end: validatedDates.end
    }
    
    // 修复：拖动时动态调整时间轴，让时间轴跟随拖动移动
    const newEndDate = new Date(finalDates.end)
    const newEnterDate = new Date(finalDates.enter)
    const currentFirstDate = monthDates[0]
    const currentLastDate = monthDates[monthDates.length - 1]
    
    // 当拖动的任务超出当前可视范围时，调整时间轴
    if (newEndDate > currentLastDate || newEnterDate < currentFirstDate) {
      // 计算需要调整的天数，让拖动的任务保持在可视范围内
      let daysToShift = 0
      
      if (newEndDate > currentLastDate) {
        // 向右拖动超出范围，时间轴向右移动
        daysToShift = Math.ceil((newEndDate - currentLastDate) / (24 * 60 * 60 * 1000))
      } else if (newEnterDate < currentFirstDate) {
        // 向左拖动超出范围，时间轴向左移动
        daysToShift = -Math.ceil((currentFirstDate - newEnterDate) / (24 * 60 * 60 * 1000))
      }
      
      if (daysToShift !== 0) {
        const newStartDate = new Date(startDateRef.current)
        newStartDate.setDate(newStartDate.getDate() + daysToShift)
        setStartDate(newStartDate)
        startDateRef.current = newStartDate
      }
    }
    
    // 更新可调整数据
    setAdjustableData(prev => {
      // 确保数组存在
      if (!prev[dragState.type] || !Array.isArray(prev[dragState.type])) {
        return {
          ...prev,
          [dragState.type]: [{ ...dragState.experiment, ...finalDates }]
        }
      }
      
      const updatedData = {
        ...prev,
        [dragState.type]: prev[dragState.type].map(exp =>
          exp.id === dragState.experiment.id
            ? { 
                ...exp, 
                ...finalDates
              }
            : exp
        )
      }
      
      return updatedData
    })
  }

  const handleMouseUp = (e) => {
    if (dragState) {
      // 重新计算最终位置，确保获取到正确的拖动后时间
      const deltaX = e.clientX - dragState.startX
      const containerWidth = dragState.containerRect.width
      const monthDates = getMonthDates()
      const daysToMove = Math.round((deltaX / containerWidth) * monthDates.length)
      
      let finalDates = { ...dragState.originalDates }
      
      if (daysToMove !== 0) {
        let newDates = {}
        
        if (dragState.timeKey) {
          // 单独拖拽某个时间点
          Object.keys(dragState.originalDates).forEach(key => {
            if (key === dragState.timeKey) {
              const originalDate = new Date(dragState.originalDates[key])
              originalDate.setDate(originalDate.getDate() + daysToMove)
              newDates[key] = originalDate.toISOString().split('T')[0]
            } else {
              newDates[key] = dragState.originalDates[key]
            }
          })
          
          // 特殊处理：拖拽开始时间或完成时间时的约束，防止拖动条重叠
          const MIN_INTERVAL_MS = 24 * 60 * 60 * 1000 // 1天的毫秒数
          
          if (dragState.timeKey === 'start') {
            // 拖拽开始时间时，确保与完成时间保持最小间隔
            const newStartDate = new Date(newDates.start)
            const completeDate = new Date(newDates.complete)
            const maxAllowedStartTime = completeDate.getTime() - MIN_INTERVAL_MS
            
            if (newStartDate.getTime() > maxAllowedStartTime) {
              newDates.start = new Date(maxAllowedStartTime).toISOString().split('T')[0]
            }
          } else if (dragState.timeKey === 'complete') {
            // 拖拽完成时间时，确保与开始时间保持最小间隔
            const startDate = new Date(newDates.start)
            const newCompleteDate = new Date(newDates.complete)
            const minAllowedCompleteTime = startDate.getTime() + MIN_INTERVAL_MS
            
            if (newCompleteDate.getTime() < minAllowedCompleteTime) {
              newDates.complete = new Date(minAllowedCompleteTime).toISOString().split('T')[0]
            }
          }
        } else {
          // 整体拖拽甘特图
          Object.keys(dragState.originalDates).forEach(key => {
            const originalDate = new Date(dragState.originalDates[key])
            originalDate.setDate(originalDate.getDate() + daysToMove)
            newDates[key] = originalDate.toISOString().split('T')[0]
          })
        }
        
        // 验证时间约束
        const validatedDates = validateAndAdjustExperimentTimes(newDates)
        finalDates = {
          enter: validatedDates.enter,
        start: validatedDates.start,
        complete: validatedDates.complete,
        end: validatedDates.end
        }
      }
      
      console.log('✅ 拖动任务块完成:', {
        设备: dragState.equipment?.name || dragState.equipment?.equipment_name || '未知设备',
        试验类型: dragState.type,
        试验名称: dragState.experiment?.experiment_name || dragState.experiment?.name || '未知试验',
        拖动距离: `${daysToMove}天`,
        拖动前时间: {
          入场时间: dragState.originalDates.enter,
          开始时间: dragState.originalDates.start,
          完成时间: dragState.originalDates.complete,
          出场时间: dragState.originalDates.end
        },
        拖动后时间: {
          入场时间: finalDates.enter,
          开始时间: finalDates.start,
          完成时间: finalDates.complete,
          出场时间: finalDates.end
        },
        时间变化: {
          入场时间变化: dragState.originalDates.enter !== finalDates.enter,
          开始时间变化: dragState.originalDates.start !== finalDates.start,
          完成时间变化: dragState.originalDates.complete !== finalDates.complete,
          出场时间变化: dragState.originalDates.end !== finalDates.end
        }
      })
    }
    setDragState(null)
  }

  // 从API加载设备数据
  const loadEquipments = async () => {
    try {
      setLoading(true)
      const data = await experimentPlanningAPI.equipment.getAll()
      setEquipments(data.results || data) // 处理分页和非分页响应
      setError(null)
    } catch (error) {
      console.error('加载设备数据失败:', error)
      setError('加载设备数据失败')
    } finally {
      setLoading(false)
    }
  }

  // 从API加载试验计划数据
  const loadExperimentData = async () => {
    try {
      const ganttData = await experimentPlanningAPI.experimentPlan.getGanttData()
      
      // 根据数据自动设置起始日期
      const allExperiments = [...(ganttData.整星试验 || []), ...(ganttData.单机试验 || []), ...(ganttData.自建试验 || [])]
      if (allExperiments.length > 0) {
        const allDates = allExperiments.flatMap(exp => [
          exp.enter,
          exp.start,
          exp.complete,
          exp.end
        ]).filter(date => date).map(date => new Date(date))
        
        if (allDates.length > 0) {
          const earliestDate = new Date(Math.min(...allDates))
          // 设置为该月的第一天
          const startOfMonth = new Date(earliestDate.getFullYear(), earliestDate.getMonth(), 1)
          setStartDate(startOfMonth)
          startDateRef.current = startOfMonth
        }
      }
      
      // 分离可拖动和不可拖动的数据
      const systemDataFiltered = {
        整星试验: (ganttData.整星试验 || []).filter(exp => !exp.is_adjustable),
        单机试验: (ganttData.单机试验 || []).filter(exp => !exp.is_adjustable),
        自建试验: (ganttData.自建试验 || []).filter(exp => !exp.is_adjustable)
      }
      
      const adjustableDataFiltered = {
        整星试验: (ganttData.整星试验 || []).filter(exp => exp.is_adjustable),
        单机试验: (ganttData.单机试验 || []).filter(exp => exp.is_adjustable),
        自建试验: (ganttData.自建试验 || []).filter(exp => exp.is_adjustable)
      }
      
      setSystemData(systemDataFiltered)
      setAdjustableData(adjustableDataFiltered)
    } catch (error) {
      console.error('加载试验计划数据失败:', error)
      // 设置空数据
      setSystemData({})
      setAdjustableData({})
    }
  }



  // 初始化数据
  useEffect(() => {
    startDateRef.current = startDate
    loadEquipments()
    loadExperimentData()
    
    // 添加全局点击事件来隐藏右键菜单
    const handleGlobalClick = () => {
      hideContextMenu()
    }
    
    document.addEventListener('click', handleGlobalClick)
    document.addEventListener('contextmenu', handleGlobalClick)
    
    return () => {
      document.removeEventListener('click', handleGlobalClick)
      document.removeEventListener('contextmenu', handleGlobalClick)
    }
  }, [])

  // 同步startDateRef
  useEffect(() => {
    startDateRef.current = startDate
  }, [startDate])



  useEffect(() => {
    if (dragState) {
      document.addEventListener('mousemove', handleMouseMove)
      document.addEventListener('mouseup', handleMouseUp)
      return () => {
        document.removeEventListener('mousemove', handleMouseMove)
        document.removeEventListener('mouseup', handleMouseUp)
      }
    }
  }, [dragState])



  const monthDates = getMonthDates()

  // 获取指定设备的系统数据
  const getEquipmentSystemData = (equipmentName) => {
    const satelliteExp = systemData.整星试验?.find(exp => exp.equipment === equipmentName)
    const componentExp = systemData.单机试验?.find(exp => exp.equipment === equipmentName)
    const customExp = systemData.自建试验?.find(exp => exp.equipment === equipmentName)
    return { satelliteExp, componentExp, customExp }
  }
  
  // 获取指定设备的可调整数据
  const getEquipmentAdjustableData = (equipmentName) => {
    const satelliteExp = adjustableData.整星试验?.find(exp => exp.equipment === equipmentName)
    const componentExp = adjustableData.单机试验?.find(exp => exp.equipment === equipmentName)
    const customExp = adjustableData.自建试验?.find(exp => exp.equipment === equipmentName)
    return { satelliteExp, componentExp, customExp }
  }

  // 检测甘特图重叠冲突（检测同一行内所有甘特图的重叠）
  const detectConflicts = (equipmentName) => {
    const systemExperiments = getEquipmentSystemData(equipmentName)
    const adjustableExperiments = getEquipmentAdjustableData(equipmentName)
    
    const conflicts = []
    
    // 收集系统数据行的所有试验
    const systemExps = []
    if (systemExperiments.satelliteExp) {
      systemExps.push({ ...systemExperiments.satelliteExp, source: 'system', type: '整星试验' })
    }
    if (systemExperiments.componentExp) {
      systemExps.push({ ...systemExperiments.componentExp, source: 'system', type: '单机试验' })
    }
    if (systemExperiments.customExp) {
      systemExps.push({ ...systemExperiments.customExp, source: 'system', type: '自建试验' })
    }
    
    // 收集可调整数据行的所有试验
    const adjustableExps = []
    if (adjustableExperiments.satelliteExp) {
      adjustableExps.push({ ...adjustableExperiments.satelliteExp, source: 'adjustable', type: '整星试验' })
    }
    if (adjustableExperiments.componentExp) {
      adjustableExps.push({ ...adjustableExperiments.componentExp, source: 'adjustable', type: '单机试验' })
    }
    if (adjustableExperiments.customExp) {
      adjustableExps.push({ ...adjustableExperiments.customExp, source: 'adjustable', type: '自建试验' })
    }
    
    // 检测系统数据行内部的所有冲突
    for (let i = 0; i < systemExps.length; i++) {
      for (let j = i + 1; j < systemExps.length; j++) {
        const exp1 = systemExps[i]
        const exp2 = systemExps[j]
        
        const start1 = new Date(exp1.enter)
    const end1 = new Date(exp1.end)
    const start2 = new Date(exp2.enter)
    const end2 = new Date(exp2.end)
        
        // 检测时间重叠
        if (start1 <= end2 && start2 <= end1) {
          const overlapStart = new Date(Math.max(start1.getTime(), start2.getTime()))
          const overlapEnd = new Date(Math.min(end1.getTime(), end2.getTime()))
          
          conflicts.push({
            exp1,
            exp2,
            overlapStart: overlapStart.toISOString().split('T')[0],
            overlapEnd: overlapEnd.toISOString().split('T')[0],
            overlapStartFormatted: `${overlapStart.getMonth() + 1}.${overlapStart.getDate()}`,
            overlapEndFormatted: `${overlapEnd.getMonth() + 1}.${overlapEnd.getDate()}`,
            area: 'system' // 标记冲突发生在系统数据区域
          })
        }
      }
    }
    
    // 检测可调整数据行内部的所有冲突
    for (let i = 0; i < adjustableExps.length; i++) {
      for (let j = i + 1; j < adjustableExps.length; j++) {
        const exp1 = adjustableExps[i]
        const exp2 = adjustableExps[j]
        
        const start1 = new Date(exp1.enter)
    const end1 = new Date(exp1.end)
    const start2 = new Date(exp2.enter)
    const end2 = new Date(exp2.end)
        
        // 检测时间重叠
        if (start1 <= end2 && start2 <= end1) {
          const overlapStart = new Date(Math.max(start1.getTime(), start2.getTime()))
          const overlapEnd = new Date(Math.min(end1.getTime(), end2.getTime()))
          
          conflicts.push({
            exp1,
            exp2,
            overlapStart: overlapStart.toISOString().split('T')[0],
            overlapEnd: overlapEnd.toISOString().split('T')[0],
            overlapStartFormatted: `${overlapStart.getMonth() + 1}.${overlapStart.getDate()}`,
            overlapEndFormatted: `${overlapEnd.getMonth() + 1}.${overlapEnd.getDate()}`,
            area: 'adjustable' // 标记冲突发生在可调整数据区域
          })
        }
      }
    }
    
    return conflicts
  }
  
  // 渲染重叠高亮
  const renderOverlapHighlight = (conflict) => {
    const overlapPosition = getExperimentPosition({
      enter: conflict.overlapStart,
      end: conflict.overlapEnd
    }, monthDates)
    
    if (!overlapPosition) return null
    
    return (
      <div
        key={`overlap-${conflict.overlapStart}-${conflict.overlapEnd}`}
        style={{
          position: 'absolute',
          left: overlapPosition.left,
          width: overlapPosition.width,
          height: '100%',
          background: 'rgba(255, 0, 0, 0.3)',
          border: '2px solid #ff4d4f',
          borderRadius: '4px',
          zIndex: 20,
          pointerEvents: 'none'
        }}
        title={`冲突时间段: ${conflict.overlapStartFormatted}-${conflict.overlapEndFormatted}`}
      />
    )
  }
  
  // 修改设备列渲染，添加冲突提示
  const renderEquipmentWithConflict = (equipment) => {
    const conflicts = detectConflicts(equipment.name)
    const hasConflict = conflicts.length > 0
    
    return (
      <div 
        key={equipment.id}
        style={{
          borderBottom: '1px solid #e8e8e8',
          height: '96px', // 更新高度从72px到96px
          minHeight: '96px', // 确保最小高度
          background: '#fafafa',
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'center',
          alignItems: 'center',
          padding: '3px',
          boxSizing: 'border-box',
          position: 'relative'
        }}
      >
        {/* 冲突警示图标 */}
        {hasConflict && (
          <div
            style={{
              position: 'absolute',
              top: '2px',
              left: '2px',
              width: '16px',
              height: '16px',
              background: '#ff4d4f',
              borderRadius: '50%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              color: 'white',
              fontSize: '10px',
              fontWeight: 'bold',
              zIndex: 25
            }}
            title={`时间冲突: ${conflicts.map(c => `${c.overlapStartFormatted}-${c.overlapEndFormatted}`).join(', ')}`}
          >
            !
          </div>
        )}
        
        <div 
          style={{ 
            height: '100%', 
            width: '100%',
            display: 'flex',
            flexDirection: 'column',
            justifyContent: 'center',
            alignItems: 'center'
          }}
        >
          <div style={{ 
            fontSize: '11px',
            fontWeight: '600', 
            textAlign: 'center',
            lineHeight: '1.2',
            marginBottom: '2px'
          }}>
            {equipment.name}
          </div>
          <div style={{ 
            fontSize: '9px',
            color: '#666', 
            textAlign: 'center',
            lineHeight: '1.1'
          }}>
            负责人：{equipment.responsible}
          </div>
        </div>
      </div>
    )
  }

  // 渲染时间段标记（修改虚线延伸到日期表头）
  const renderTimeMarkers = (experiment, isDraggable = false, type = '', equipment = '') => {
    if (!experiment || !monthDates || monthDates.length === 0) return null;
    
    const position = getExperimentPosition(experiment, monthDates)
    if (!position) return null
    
    const timePoints = [
      { key: 'enter', label: '入场', color: '#52c41a', date: experiment.enter },
    { key: 'start', label: '开始', color: '#1890ff', date: experiment.start },
    { key: 'complete', label: '完成', color: '#722ed1', date: experiment.complete },
    { key: 'end', label: '出场', color: '#f5222d', date: experiment.end }
    ]
    
    const verticalOffset = '50%'
    
    // 处理时间点拖拽
    const handleTimePointMouseDown = (e, timeKey) => {
      if (!isDraggable) return
      e.preventDefault()
      e.stopPropagation()
      
      const rect = e.currentTarget.parentElement.getBoundingClientRect()
      const startX = e.clientX
      
      setDragState({
        experiment,
        type,
        equipment,
        timeKey,
        startX,
        containerRect: rect,
        originalDates: {
          enter: experiment.enter,
        start: experiment.start,
        complete: experiment.complete,
        end: experiment.end
        }
      })
    }
    
    return (
      <div
        style={{
          position: 'absolute',
          left: position.left,
          width: position.width,
          height: '100%',
          cursor: isDraggable ? 'move' : 'default',
          userSelect: 'none',
          transition: isDraggable ? 'all 0.2s ease' : 'none'
        }}
        className={isDraggable ? 'draggable-task-block' : 'static-task-block'}
        onMouseDown={isDraggable ? (e) => {
          // 检查是否是双击事件，双击打开编辑弹窗
          if (e.detail === 2) {
            e.preventDefault()
            e.stopPropagation()
            handleEditExperiment(experiment, type, equipment)
            return
          }
          // 单击进行拖拽
          handleMouseDown(e, experiment, type, equipment)
        } : undefined}
        onClick={isDraggable ? (e) => {
          // 单击事件处理（如果需要的话）
          if (e.detail === 1) {
            // 可以在这里添加单击逻辑
          }
        } : undefined}
        onContextMenu={isDraggable ? (e) => {
          handleContextMenu(e, experiment, type, equipment)
        } : undefined}
      >
        {/* 背景条 - 矩形 */}
        <div
          className={`task-background ${type === '单机试验' ? 'component-type' : 'satellite-type'}`}
          style={{
            position: 'absolute',
            top: verticalOffset,
            transform: 'translateY(-50%)',
            width: '100%',
            height: '30px',
            background: type === '整星试验' 
              ? 'rgba(52, 152, 219, 0.6)' 
              : type === '单机试验'
              ? 'rgba(243, 156, 18, 0.6)'
              : 'rgba(155, 89, 182, 0.6)', // 自建试验使用紫色
            borderRadius: isDraggable ? '4px' : '0px',
            border: `2px solid ${type === '整星试验' ? '#3498db' : type === '单机试验' ? '#f39c12' : '#9b59b6'}`,
            boxShadow: type === '整星试验' 
              ? '0 3px 8px rgba(52, 152, 219, 0.4)' 
              : type === '单机试验'
              ? '0 3px 8px rgba(243, 156, 18, 0.4)'
              : '0 3px 8px rgba(155, 89, 182, 0.4)', // 自建试验阴影
            display: 'flex',
            alignItems: 'center',
            paddingLeft: '8px',
            overflow: 'hidden',
            // 可调整任务块添加纹理效果
            backgroundImage: isDraggable 
              ? 'repeating-linear-gradient(45deg, transparent, transparent 2px, rgba(255,255,255,0.1) 2px, rgba(255,255,255,0.1) 4px)'
              : 'none',
            // 不可调整任务块添加灰色遮罩效果
            opacity: isDraggable ? 1 : 0.7
          }}
        >
          {/* 可调整状态指示器 */}
          {isDraggable && (
            <div style={{
              position: 'absolute',
              top: '2px',
              right: '2px',
              width: '16px',
              height: '16px',
              background: 'rgba(0, 0, 0, 0.6)',
              borderRadius: '2px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              color: 'white',
              fontSize: '8px',
              fontWeight: 'bold',
              zIndex: 20,
              cursor: 'move'
            }}>
              ⋮⋮
            </div>
          )}
          
          {/* 不可调整状态指示器 */}
          {!isDraggable && (
            <div style={{
              position: 'absolute',
              top: '2px',
              right: '2px',
              width: '16px',
              height: '16px',
              background: 'rgba(149, 165, 166, 0.8)',
              borderRadius: '2px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              color: 'white',
              fontSize: '10px',
              fontWeight: 'bold',
              zIndex: 20
            }}>
              🔒
            </div>
          )}
          
          {/* 显示钉钉数据字段 - 在所有任务块中显示 */}
          <div style={{
            fontSize: '10px',
            color: isDraggable ? '#000' : '#666',
            fontWeight: 'bold',
            textShadow: isDraggable ? '1px 1px 2px rgba(255,255,255,0.8)' : 'none',
            whiteSpace: 'nowrap',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            textAlign: 'center',
            width: '100%',
            display: 'flex',
            flexDirection: 'column',
            justifyContent: 'center',
            alignItems: 'center',
            lineHeight: '1.2',
            paddingRight: '18px' // 为右上角指示器留出空间
          }}>
            {/* 显示试验项目名称 */}
            {(experiment.experiment_name || experiment.name || experiment.experiment_report_name) && (
              <div 
                style={{ 
                  marginBottom: '2px',
                  fontSize: '9px',
                  color: '#2c3e50',
                  fontWeight: 'bold',
                  maxWidth: '100%',
                  overflow: 'hidden',
                  textOverflow: 'ellipsis',
                  cursor: 'pointer'
                }}
                onMouseEnter={(e) => showTooltip(e, experiment, type, equipment)}
                onMouseLeave={hideTooltip}
              >
                {experiment.experiment_name || experiment.name || experiment.experiment_report_name}
              </div>
            )}
            
            {/* 显示时间信息 */}
            <div style={{ display: 'flex', fontSize: '8px' }}>
              {(experiment.enter || experiment.enter_date) && (
                <span style={{ marginRight: '6px' }}>
                  入场: {experiment.enter || experiment.enter_date}
                </span>
              )}
              {(experiment.end || experiment.end_date) && (
                <span>
                  出场: {experiment.end || experiment.end_date}
                </span>
              )}
            </div>
          </div>
        </div>
        
        {/* 时间分割竖线和虚线延伸 */}
        {timePoints.map((point, index) => {
          let relativePercent
          
          if (index === 3) { // 出场时间 - 与甘特图右边界重合
            relativePercent = 100
          } else {
            const pointPosition = getTimePosition(point.date, monthDates)
            if (!pointPosition) return null
            
            const positionPercent = parseFloat(pointPosition)
            const containerPercent = parseFloat(position.left)
            relativePercent = ((positionPercent - containerPercent) / parseFloat(position.width)) * 100
          }
          
          // 只为中间两个时间点（开始和完成）绘制甘特图内的竖线
          const showInternalLine = index === 1 || index === 2 // start 和 complete
          const isDraggableTimePoint = isDraggable && showInternalLine
          
          return (
            <div key={point.key}>
              {/* 甘特图内的竖线分割（仅开始和完成时间） */}
              {showInternalLine && (
                <div
                  style={{
                    position: 'absolute',
                    left: `${relativePercent}%`,
                    top: verticalOffset,
                    transform: 'translateY(-50%) translateX(-50%)',
                    width: isDraggable ? '6px' : '2px',
                    height: '30px',
                    background: isDraggable 
                      ? `linear-gradient(to bottom, ${point.color}, ${point.color}dd)` 
                      : `${point.color}88`,
                    cursor: isDraggableTimePoint ? 'ew-resize' : 'default',
                    zIndex: 15,
                    borderRadius: isDraggable ? '3px' : '0px',
                    boxShadow: isDraggable ? `0 2px 4px ${point.color}44` : 'none',
                    border: isDraggable ? `1px solid ${point.color}` : 'none'
                  }}
                  onMouseDown={isDraggableTimePoint ? (e) => handleTimePointMouseDown(e, point.key) : undefined}
                />
              )}
              
              {/* 可拖动区域的日期标签 */}
              {isDraggable && (
                <div
                  style={{
                    position: 'absolute',
                    left: `${relativePercent}%`,
                    top: verticalOffset, // 使用与甘特图条相同的垂直位置
                    transform: 'translateX(-50%) translateY(-50%)', // 垂直和水平居中
                    fontSize: '8px',
                    color: point.color,
                    fontWeight: 'bold',
                    textShadow: '1px 1px 2px rgba(255,255,255,0.8)',
                    whiteSpace: 'nowrap',
                    zIndex: 16,
                    pointerEvents: 'none',
                    textAlign: 'center',
                    background: 'rgba(255,255,255,0.9)',
                    padding: '1px 3px',
                    borderRadius: '2px',
                    border: `1px solid ${point.color}`,
                    minWidth: '40px'
                  }}
                >
                  <div style={{ fontSize: '7px' }}>{point.label}</div>
                  <div style={{ fontSize: '6px', marginTop: '1px' }}>{point.date}</div>
                </div>
              )}
              

            </div>
          )
        })}
      </div>
    )
  }

  // 保存甘特图数据
  const handleSaveGanttData = async () => {
    try {
      setSaveStatus('saving')
      
      // 获取所有可调整的试验数据
      const allAdjustableExperiments = [
        ...(adjustableData.整星试验 || []),
        ...(adjustableData.单机试验 || []),
        ...(adjustableData.自建试验 || [])
      ]
      
      const adjustableExperiments = allAdjustableExperiments.filter(exp => exp.is_adjustable)
      
      if (adjustableExperiments.length === 0) {
        setSaveStatus('error')
        alert('没有可保存的调整数据')
        setTimeout(() => setSaveStatus('idle'), 2000)
        return
      }
      
      // 记录保存前的数据变化
      console.log('💾 保存甘特图数据 - 共', adjustableExperiments.length, '个可调整任务')
      adjustableExperiments.forEach(exp => {
        // 查找对应的系统数据以对比变化
        const systemExp = [...(systemData.整星试验 || []), ...(systemData.单机试验 || []), ...(systemData.自建试验 || [])]
          .find(sysExp => sysExp.id === exp.id)
        
        if (systemExp) {
          console.log('📊 任务更新对比:', {
            设备: exp.equipment || exp.equipment_name || '未知设备',
            试验名称: exp.experiment_name || exp.name || '未知试验',
            更新前时间: {
              入场时间: systemExp.enter,
        开始时间: systemExp.start,
        完成时间: systemExp.complete,
        出场时间: systemExp.end
            },
            更新后时间: {
              入场时间: exp.enter,
        开始时间: exp.start,
        完成时间: exp.complete,
        出场时间: exp.end
            }
          })
        }
      })
      
      // 批量更新试验时间和名称
      const updatePromises = adjustableExperiments.map(exp => {
        const updateData = {
          enter_date: exp.enter,
        start_date: exp.start,
        complete_date: exp.complete,
        end_date: exp.end,
        experiment_report_name: exp.experiment_name || exp.name // 添加试验名称字段
        }

        return experimentPlanningAPI.experimentPlan.updateDates(exp.id, updateData)
      })
      
      await Promise.all(updatePromises)
      
      // 只更新systemData中可拖动任务的日期，保持不可拖动任务不变
      setSystemData(prev => {
        const newSystemData = { ...prev }
        adjustableExperiments.forEach(exp => {
          const expType = exp.experiment_type === '整星试验' ? '整星试验' : 
                         exp.experiment_type === '单机试验' ? '单机试验' : 
                         exp.experiment_type === '自建试验' ? '自建试验' : '整星试验'
          if (newSystemData[expType]) {
            const index = newSystemData[expType].findIndex(item => item.id === exp.id)
            if (index !== -1 && newSystemData[expType][index].is_adjustable) {
              // 只更新可拖动任务的日期和名称字段
              newSystemData[expType][index] = {
                ...newSystemData[expType][index],
                enter: exp.enter,
                start: exp.start,
                complete: exp.complete,
                end: exp.end,
                experiment_name: exp.experiment_name || exp.name, // 同步试验名称
                name: exp.experiment_name || exp.name // 兼容不同字段名
              }
            }
          }
        })
        return newSystemData
      })
      
      // 保存成功后只更新systemData中对应的可拖动任务，保持adjustableData的用户调整状态
      // 不调用loadExperimentData()以避免重置adjustableData
      
      setSaveStatus('success')
      // 2秒后恢复默认状态
      setTimeout(() => setSaveStatus('idle'), 2000)
    } catch (error) {
      console.error('保存失败:', error)
      setSaveStatus('error')
      alert('保存失败，请重试')
      setTimeout(() => setSaveStatus('idle'), 2000)
    }
  }

  return (
    <div className="card" style={{ overflowX: 'hidden' }}> {/* 防止页面横向滚动 */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '24px' }}>
        <h2>试验任务总览</h2>
        <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
          {/* 添加试验按钮 */}
          <button
            onClick={handleOpenAddModal}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: '8px',
              padding: '8px 16px',
              backgroundColor: '#52c41a',
              color: 'white',
              border: 'none',
              borderRadius: '6px',
              cursor: 'pointer',
              fontSize: '14px',
              fontWeight: '500',
              transition: 'all 0.3s ease'
            }}
            onMouseOver={(e) => {
              e.target.style.backgroundColor = '#73d13d'
            }}
            onMouseOut={(e) => {
              e.target.style.backgroundColor = '#52c41a'
            }}
          >
            <Plus size={16} />
            添加试验
          </button>
          
          {/* 保存按钮 */}
          <button
            onClick={handleSaveGanttData}
            disabled={saveStatus === 'saving'}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: '8px',
              padding: '8px 16px',
              backgroundColor: saveStatus === 'saving' ? '#d9d9d9' : 
                             saveStatus === 'success' ? '#52c41a' : 
                             saveStatus === 'error' ? '#ff4d4f' : '#1890ff',
              color: 'white',
              border: 'none',
              borderRadius: '6px',
              cursor: saveStatus === 'saving' ? 'not-allowed' : 'pointer',
              fontSize: '14px',
              fontWeight: '500',
              transition: 'all 0.3s ease'
            }}
            onMouseOver={(e) => {
              if (saveStatus === 'idle') {
                e.target.style.backgroundColor = '#40a9ff'
              }
            }}
            onMouseOut={(e) => {
              if (saveStatus === 'idle') {
                e.target.style.backgroundColor = '#1890ff'
              }
            }}
          >
            <Save size={16} />
            {saveStatus === 'saving' ? '保存中...' : 
             saveStatus === 'success' ? '保存成功' : 
             saveStatus === 'error' ? '保存失败' : '保存'}
          </button>
        </div>
      </div>

      {/* 时间节点说明 */}
      <div style={{ 
        marginBottom: '20px', 
        padding: '8px 12px', 
        background: '#f6f8fa', 
        border: '1px solid #e1e4e8', 
        borderRadius: '6px',
        fontSize: '14px'
      }}>
        <div style={{ marginBottom: '8px' }}>
          <strong>时间节点：</strong>
          <span style={{ color: '#52c41a', marginLeft: '8px' }}>●入场</span>
          <span style={{ color: '#1890ff', marginLeft: '8px' }}>●开始</span>
          <span style={{ color: '#722ed1', marginLeft: '8px' }}>●完成</span>
          <span style={{ color: '#f5222d', marginLeft: '8px' }}>●出场</span>
        </div>
        <div>
          <strong>试验类型：</strong>
          <span style={{ 
            marginLeft: '8px', 
            padding: '2px 6px', 
            background: 'rgba(52, 152, 219, 0.1)', 
            border: '1px solid #3498db', 
            borderRadius: '3px',
            fontSize: '12px'
          }}>
            整星试验
          </span>
          <span style={{ 
            marginLeft: '8px', 
            padding: '2px 6px', 
            background: 'rgba(243, 156, 18, 0.1)', 
            border: '1px solid #f39c12', 
            borderRadius: '3px',
            fontSize: '12px'
          }}>
            单机试验
          </span>
          <span style={{ 
            marginLeft: '8px', 
            padding: '2px 6px', 
            background: 'rgba(155, 89, 182, 0.1)', 
            border: '1px solid #9b59b6', 
            borderRadius: '3px',
            fontSize: '12px'
          }}>
            自建试验
          </span>
        </div>
        <div style={{ marginTop: '8px', fontSize: '12px', color: '#666' }}>
          <strong>操作提示：</strong>按住 Shift 键并滚动鼠标滚轮可横向查看日期
        </div>
      </div>

      {/* 甘特图表头 */}
      <div style={{ marginBottom: '16px' }}>
        {/* 标题居中 */}
        <h3 style={{ marginBottom: '12px', textAlign: 'center' }}>
          试验任务甘特图
        </h3>
      </div>

      {/* 冻结甘特图容器 */}
      <div 
        ref={ganttContainerRef}
        style={{
          position: 'relative',
          height: 'calc(100vh - 200px)',
          minHeight: '600px', // 确保最小高度
          maxHeight: 'calc(100vh - 200px)',
          overflowY: 'auto',  // 改为 auto 以启用垂直滚动
          overflowX: 'hidden',  // 保持隐藏横向溢出
          width: '100%',
          maxWidth: '100%',
          boxSizing: 'border-box',
          border: '1px solid #e8e8e8', // 添加边框以明确容器边界
          borderRadius: '4px'
        }}
        onWheel={handleWheel}
      >
        {/* 日期表头 - 固定在顶部 */}
        <div style={{
          position: 'sticky',
          top: 0,
          zIndex: 20,
          background: 'white',
          borderBottom: '2px solid #e8e8e8',
          display: 'flex',
          height: '50px',
          flexShrink: 0
        }}>
          {/* 设备列表头 - 冻结 */}
          <div style={{
            width: '100px',
            flexShrink: 0,
            padding: '4px',
            background: '#f5f5f5',
            fontWeight: '600',
            borderRight: '2px solid #e8e8e8',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            fontSize: '12px',
            position: 'sticky',
            left: 0,
            zIndex: 21
          }}>
            试验设备
          </div>
          
          {/* 日期表头滚动区域 - 严格控制宽度 */}
          <div 
            className="date-header-scroll"
            style={{
              width: 'calc(100% - 102px)', // 减去设备列宽度和边框
              maxWidth: 'calc(100% - 102px)',
              overflowX: 'auto',
              overflowY: 'hidden',
              scrollbarWidth: 'none',
              msOverflowStyle: 'none',
              boxSizing: 'border-box'
            }}
            onScroll={handleHorizontalScroll}
          >
            <style>
              {`.date-header-scroll::-webkit-scrollbar { display: none; }`}
              {`
                .draggable-task-block:hover {
                  transform: translateY(-1px);
                  filter: brightness(1.1);
                }
                .draggable-task-block:hover .task-background {
                  box-shadow: 0 6px 16px rgba(52, 152, 219, 0.6) !important;
                  border-width: 4px !important;
                }
                .draggable-task-block:hover .task-background.component-type {
                  box-shadow: 0 6px 16px rgba(243, 156, 18, 0.6) !important;
                }
                .static-task-block {
                  pointer-events: none;
                }
                .static-task-block .task-background {
                  filter: grayscale(20%);
                }
              `}
            </style>
            <div style={{
              display: 'flex',
              background: '#f5f5f5',
              minWidth: `${monthDates.length * 40}px`,  // 现在为 60 * 40 = 2400px，确保超过典型宽度
              width: `${monthDates.length * 40}px`
            }}>
              {monthDates.map(date => {
                const isWeekend = date.getDay() === 0 || date.getDay() === 6
                const isHolidayDate = isHoliday(date)
                const isPast = isPastDate(date)
                const month = date.getMonth() + 1
                const day = date.getDate()
                
                return (
                  <div 
                    key={date.toISOString()}
                    style={{
                      minWidth: '40px',
                      width: '40px',
                      maxWidth: '40px',
                      flexShrink: 0,
                      padding: '4px 2px',
                      textAlign: 'center',
                      fontSize: '10px',
                      borderRight: '1px solid #e8e8e8',
                      background: isPast 
                        ? '#f0f0f0' 
                        : (isHolidayDate ? '#ffebee' : (isWeekend ? '#f0f0f0' : '#f5f5f5')),
                      color: isPast 
                        ? '#999' 
                        : (isHolidayDate ? '#d32f2f' : (isWeekend ? '#666' : '#333')),
                      display: 'flex',
                      flexDirection: 'column',
                      justifyContent: 'center'
                    }}
                  >
                    <div style={{ color: isPast ? '#999' : 'inherit', lineHeight: '1.1' }}>
                      {month}.{day}
                    </div>
                    <div style={{ fontSize: '8px', color: isPast ? '#999' : '#666', lineHeight: '1.1' }}>
                      {['日', '一', '二', '三', '四', '五', '六'][date.getDay()]}
                      {!isPast && isHolidayDate && <span style={{ color: '#d32f2f' }}>假</span>}
                      {!isPast && isWeekend && !isHolidayDate && <span style={{ color: '#666' }}>休</span>}
                    </div>
                  </div>
                )
              })}
            </div>
          </div>
        </div>

        {/* 甘特图主体区域 - 统一竖向滚动 */}
        <div style={{
          flex: 1,
          minHeight: '500px', // 确保主体区域有足够的最小高度
          overflowY: 'auto',
          overflowX: 'hidden',
          width: '100%',
          maxWidth: '100%',
          boxSizing: 'border-box',
          position: 'relative', // 添加相对定位以支持虚线延伸
          paddingBottom: '50px' // 添加底部填充，确保滚动到底部时有缓冲
        }}>
          <div style={{ 
            display: 'flex',
            width: '100%',
            maxWidth: '100%',
            boxSizing: 'border-box'
          }}>
            {/* 设备列 - 横向冻结，竖向跟随滚动 */}
            <div style={{
              width: '100px',
              minWidth: '100px',
              maxWidth: '100px',
              flexShrink: 0,
              borderRight: '2px solid #e8e8e8',
              background: 'white',
              position: 'sticky',
              left: 0,
              zIndex: 10,
              boxSizing: 'border-box'
            }}>
              {loading ? (
                <div style={{
                  height: '96px', // 更新高度从72px到96px
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  color: '#666',
                  fontSize: '12px'
                }}>
                  加载中...
                </div>
              ) : error ? (
                <div style={{
                  height: '96px', // 更新高度从72px到96px
                  display: 'flex',
                  flexDirection: 'column',
                  alignItems: 'center',
                  justifyContent: 'center',
                  color: '#ff4d4f',
                  fontSize: '10px',
                  padding: '5px'
                }}>
                  <div>{error}</div>
                  <button 
                    onClick={loadEquipments}
                    style={{
                      marginTop: '5px',
                      padding: '2px 8px',
                      fontSize: '9px',
                      background: '#1890ff',
                      color: 'white',
                      border: 'none',
                      borderRadius: '3px',
                      cursor: 'pointer'
                    }}
                  >
                    重试
                  </button>
                </div>
              ) : (
                equipments.map((equipment) => renderEquipmentWithConflict(equipment))
              )}

            </div>

            {/* 甘特图内容区域 */}
            <div 
              className="content-area-scroll gantt-scroll-container"
              style={{
                width: 'calc(100% - 102px)',
                maxWidth: 'calc(100% - 102px)',
                overflowX: 'auto',
                overflowY: 'auto',
                scrollbarWidth: 'thin',
                boxSizing: 'border-box'
              }}
              onScroll={handleHorizontalScroll}
            >
              <div style={{
                minWidth: `${monthDates.length * 40}px`,
                width: `${monthDates.length * 40}px`
              }}>
                {loading ? (
                  <div style={{
                    height: '96px', // 更新高度从72px到96px
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    color: '#666',
                    fontSize: '12px'
                  }}>
                    加载试验数据中...
                  </div>
                ) : error ? (
                  <div style={{
                    height: '96px', // 更新高度从72px到96px
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    color: '#ff4d4f',
                    fontSize: '12px'
                  }}>
                    数据加载失败
                  </div>
                ) : equipments.length === 0 ? (
                  <div style={{
                    height: '96px', // 更新高度从72px到96px
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    color: '#999',
                    fontSize: '12px'
                  }}>
                    暂无设备数据
                  </div>
                ) : (
                  equipments.map((equipment) => {
                    const systemExperiments = getEquipmentSystemData(equipment.name)
                    const adjustableExperiments = getEquipmentAdjustableData(equipment.name)
                    const conflicts = detectConflicts(equipment.name)
                    
                    return (
                      <div 
                        key={equipment.id}
                        style={{
                          borderBottom: '1px solid #e8e8e8',
                          height: '96px', // 增加行高度从72px到96px
                          minHeight: '96px', // 确保最小高度
                          display: 'flex',
                          flexDirection: 'column',
                          position: 'relative'
                        }}
                      >
                      {/* 系统数据区域 */}
                      <div style={{
                        flex: 1,
                        position: 'relative',
                        background: '#f8f9fa',
                        height: '48px', // 增加高度从36px到48px
                        minHeight: '48px',
                        display: 'flex',
                        alignItems: 'center'
                      }}>
                        {systemExperiments.satelliteExp && renderTimeMarkers(systemExperiments.satelliteExp, false, '整星试验')}
                        {systemExperiments.componentExp && renderTimeMarkers(systemExperiments.componentExp, false, '单机试验')}
                        {systemExperiments.customExp && renderTimeMarkers(systemExperiments.customExp, false, '自建试验')}
                        
                        {/* 显示系统数据区域的重叠高亮 */}
                        {conflicts.filter(conflict => conflict.area === 'system').map(conflict => renderOverlapHighlight(conflict))}
                      </div>
                      
                      {/* 可调整区域 */}
                      <div style={{
                        flex: 1,
                        position: 'relative',
                        background: 'white',
                        height: '48px', // 增加高度从36px到48px
                        minHeight: '48px',
                        display: 'flex',
                        alignItems: 'center'
                      }}>
                        {adjustableExperiments.satelliteExp && renderTimeMarkers(adjustableExperiments.satelliteExp, true, '整星试验', equipment.name)}
                        {adjustableExperiments.componentExp && renderTimeMarkers(adjustableExperiments.componentExp, true, '单机试验', equipment.name)}
                        {adjustableExperiments.customExp && renderTimeMarkers(adjustableExperiments.customExp, true, '自建试验', equipment.name)}
                        
                        {/* 显示可调整数据区域的重叠高亮 */}
                        {conflicts.filter(conflict => conflict.area === 'adjustable').map(conflict => renderOverlapHighlight(conflict))}
                      </div>
                      
                      {/* 移除这里原来的重叠冲突高亮代码 */}
                      {/* {conflicts.map(conflict => renderOverlapHighlight(conflict))} */}
                    </div>
                  )
                })
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
      
      {/* 编辑弹窗 */}
      {editModalVisible && (
        <div style={{
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          backgroundColor: 'rgba(0, 0, 0, 0.5)',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          zIndex: 1000
        }}>
          <div style={{
            backgroundColor: 'white',
            borderRadius: '8px',
            padding: '24px',
            minWidth: '400px',
            maxWidth: '500px',
            boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)'
          }}>
            <h3 style={{
              margin: '0 0 20px 0',
              fontSize: '18px',
              fontWeight: '600',
              color: '#333'
            }}>
              编辑试验信息
            </h3>
            
            <div style={{ marginBottom: '16px' }}>
              <label style={{
                display: 'block',
                marginBottom: '6px',
                fontSize: '14px',
                fontWeight: '500',
                color: '#555'
              }}>
                试验名称
              </label>
              <input
                type="text"
                value={editForm.experiment_name}
                onChange={(e) => setEditForm(prev => ({ ...prev, experiment_name: e.target.value }))}
                style={{
                  width: '100%',
                  padding: '8px 12px',
                  border: '1px solid #d9d9d9',
                  borderRadius: '4px',
                  fontSize: '14px',
                  boxSizing: 'border-box'
                }}
                placeholder="请输入试验名称"
              />
            </div>
            
            <div style={{ marginBottom: '16px' }}>
              <label style={{
                display: 'block',
                marginBottom: '6px',
                fontSize: '14px',
                fontWeight: '500',
                color: '#555'
              }}>
                入场时间
              </label>
              <input
                type="date"
                value={editForm.enter}
                onChange={(e) => setEditForm(prev => ({ ...prev, enter: e.target.value }))}
                style={{
                  width: '100%',
                  padding: '8px 12px',
                  border: '1px solid #d9d9d9',
                  borderRadius: '4px',
                  fontSize: '14px',
                  boxSizing: 'border-box'
                }}
              />
            </div>
            
            <div style={{ marginBottom: '24px' }}>
              <label style={{
                display: 'block',
                marginBottom: '6px',
                fontSize: '14px',
                fontWeight: '500',
                color: '#555'
              }}>
                出场时间
              </label>
              <input
                type="date"
                value={editForm.end}
                onChange={(e) => setEditForm(prev => ({ ...prev, end: e.target.value }))}
                style={{
                  width: '100%',
                  padding: '8px 12px',
                  border: '1px solid #d9d9d9',
                  borderRadius: '4px',
                  fontSize: '14px',
                  boxSizing: 'border-box'
                }}
              />
            </div>
            
            <div style={{
              display: 'flex',
              justifyContent: 'flex-end',
              gap: '12px'
            }}>
              <button
                onClick={handleCloseEditModal}
                style={{
                  padding: '8px 16px',
                  border: '1px solid #d9d9d9',
                  borderRadius: '4px',
                  backgroundColor: 'white',
                  color: '#666',
                  fontSize: '14px',
                  cursor: 'pointer'
                }}
              >
                取消
              </button>
              <button
                onClick={handleSaveEdit}
                style={{
                  padding: '8px 16px',
                  border: 'none',
                  borderRadius: '4px',
                  backgroundColor: '#1890ff',
                  color: 'white',
                  fontSize: '14px',
                  cursor: 'pointer'
                }}
              >
                保存
              </button>
            </div>
          </div>
        </div>
      )}
      
      {/* Tooltip组件 */}
      {tooltip.visible && tooltip.content && (
        <div
          style={{
            position: 'fixed',
            left: tooltip.x,
            top: tooltip.y,
            transform: 'translateX(-50%) translateY(-100%)',
            background: 'rgba(0, 0, 0, 0.9)',
            color: 'white',
            padding: '12px 16px',
            borderRadius: '8px',
            fontSize: '12px',
            lineHeight: '1.4',
            zIndex: 1000,
            maxWidth: '300px',
            boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            pointerEvents: 'none'
          }}
        >
          <div style={{ fontWeight: 'bold', marginBottom: '8px', color: '#4CAF50' }}>
             {tooltip.content.experiment_name}
           </div>
           <div style={{ display: 'grid', gridTemplateColumns: '80px 1fr', gap: '4px 8px' }}>
             <span style={{ color: '#ccc' }}>入场时间:</span>
             <span>{tooltip.content.enter_date}</span>
             
             <span style={{ color: '#ccc' }}>出场时间:</span>
             <span>{tooltip.content.end_date}</span>
           </div>
        </div>
      )}
      
      {/* 右键菜单 */}
      {contextMenu.visible && (
        <div
          style={{
            position: 'fixed',
            left: contextMenu.x,
            top: contextMenu.y,
            background: 'white',
            border: '1px solid #ddd',
            borderRadius: '4px',
            boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
            zIndex: 1000,
            minWidth: '120px'
          }}
          onClick={(e) => e.stopPropagation()}
        >
          <div
            style={{
              padding: '8px 16px',
              cursor: 'pointer',
              borderBottom: '1px solid #eee',
              fontSize: '14px',
              color: '#333'
            }}
            onClick={() => {
              handleEditExperiment(contextMenu.experiment, contextMenu.type, contextMenu.equipment)
              hideContextMenu()
            }}
            onMouseEnter={(e) => e.target.style.background = '#f5f5f5'}
            onMouseLeave={(e) => e.target.style.background = 'white'}
          >
            编辑试验
          </div>
          <div
            style={{
              padding: '8px 16px',
              cursor: 'pointer',
              fontSize: '14px',
              color: '#ff4d4f'
            }}
            onClick={() => {
              handleDeleteExperiment(contextMenu.experiment)
            }}
            onMouseEnter={(e) => e.target.style.background = '#fff2f0'}
            onMouseLeave={(e) => e.target.style.background = 'white'}
          >
            删除试验
          </div>
        </div>
      )}
      
      {/* 添加试验弹窗 */}
      <AddExperimentModal
        visible={addModalVisible}
        onClose={handleCloseAddModal}
        onAdd={handleAddExperiment}
        equipments={equipments}
      />
    </div>
  )
}

export default ExperimentPlanning